#include "ls_dm.h"
#include "ls_common.h"
#include "ls_trace_common.h"
#include "fhost.h"
#include "ls_ota.h"
#include "wifi_mgmr_ext.h"
#include "ls_version.h"

static pthread_t  dm_pid = NULL;
static int sockId = -1;
static char *pbuffer = NULL;
static struct sockaddr_in client_addr;
static struct sockaddr_in last_client_addr;
static uint8_t conenct = 0;

static int __ls_dm_socket_init()
{
    // create socket.
    int ret = socket(AF_INET, SOCK_DGRAM, 0);
    if (ret < 0)
    {
        LS_TRACE_ERROR("create socket error:%d!", ret);
        return -1;
    }

    struct sockaddr_in server_addr;
    server_addr.sin_port = htons(6789); // 设置本地端口号
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY; // 设置本地IP地址

    client_addr = server_addr;
    client_addr.sin_port = 9999;

    // 将套接字绑定到指定地址
    if (bind(ret,(struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        LS_TRACE_ERROR("Failed to bind socket");
        return -1;
    }

    return ret;
}



/// @brief 
/// @param pdata 
/// @return 
static void __ls_dm_msg_handle(char *pdata,int32_t datalen)
{
    if(datalen >= DSC_CHECKCODE_LEN)
    {
       
        if(strncmp(DSC_CHECKCODE,pdata,DSC_CHECKCODE_LEN) == 0)
        {
            conenct = 1;
            DEVICE_INFO *info = pdata;
            strcpy(info->ucCheckCode,DSC_CHECKCODE);
            info->ucMesType = DSC_MT_SEARCH_RESP;
            char tmpData[6];
            wifi_mgmr_sta_mac_get(tmpData);
            sprintf(info->networkInfo.ucMacAddr,"%X:%X:%X:%X:%X:%X",tmpData[0],tmpData[1],tmpData[2],tmpData[3],tmpData[4],tmpData[5]);
            info->networkInfo.ucDhcpEnable = 1;
            struct netif *netif = fhost_to_net_if(MGMR_VIF_STA);
            if(netif)
            strcpy(info->networkInfo.ucIpAddr,ip4addr_ntoa(netif_ip4_addr(netif)));
            strcpy(info->devInfo.ucDevName,LS_SERIES_NAME);
            LS_FORMAT_VERSION_STRING(info->platformInfo.ucFirmwareVersion);
            strcpy(info->platformInfo.ucP2pSerialNum,"OEMAAAF-000000-NXYYM");
            last_client_addr = client_addr;
            sendto(sockId,pdata,sizeof(DEVICE_INFO),0,&client_addr,sizeof(client_addr));
        }
        else if(strncmp(DSC_CHECKCODE_UPDATE,pdata,DSC_CHECKCODE_LEN) == 0 && conenct)
        {
            UPDATE_INFO *info =(UPDATE_INFO *)pdata;
            if(info->ucMesType == DSC_MT_SEARCH)
            {
                ls_ota_start(info->ucURL);
            }
        }
        else if(strncmp(DSC_CHECKCODE_RESET,pdata,DSC_CHECKCODE_LEN) == 0 && conenct)
        {
            LS_TRACE_DEBUG("reset is msg!");
        }
        else
        {
            LS_TRACE_ERROR("msg is error:%s!",pdata);
        }
    }
    else
    {
        LS_TRACE_ERROR("datalen is small!");
    }

}


static void *__ls_dm_task(void *p)
{
    LS_TRACE_DEBUG("dm start!");
    sockId = __ls_dm_socket_init();
    if(sockId == -1)
    {
        LS_TRACE_ERROR("socket init error!");
        vTaskDelete(NULL);
    }

#define  MAX_BUFFER_SIZE 512
    pbuffer=malloc(MAX_BUFFER_SIZE);
    socklen_t client_addr_len = sizeof(client_addr);
    fd_set  readfds;
    while (1)
    {
        FD_ZERO(&readfds);
        FD_SET(sockId, &readfds);
        struct timeval timeout={120,0};

         int ret = lwip_select(sockId+1,&readfds,NULL,NULL,&timeout);
         if(ret == 0)
         {
            conenct = 0;
            continue;
         }
         else if(ret < 0)
         {
             conenct = 0;
            LS_TRACE_ERROR("select error failed!");   
            closesocket(sockId);
            sleep(1);
            break;
         }
         else
         {
            int recv_len = recvfrom(sockId,pbuffer,MAX_BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &client_addr_len);
            if (recv_len < 0) {
                LS_TRACE_ERROR("Failed to receive data");
                break;
            }
            LS_TRACE_DEBUG("test:%d",recv_len);
            __ls_dm_msg_handle(pbuffer,recv_len);
         }
    }

    free(pbuffer);
    LS_TRACE_DEBUG("dm end!");
    vTaskDelete(NULL);
}




/// @brief 
void ls_dm_init()
{
    pthread_create(&dm_pid,NULL,__ls_dm_task,NULL);
}



/// @brief 
void ls_dm_send_update(uint32_t currCnt,uint32_t tatol)
{
    if(sockId != -1 && conenct)
    {
        UPDATE_INFO_RESP info;
        strcpy(info.ucCheckCode,DSC_CHECKCODE_UPDATE);
        info.ucMesType = DSC_MT_SEARCH_RESP;
        info.TotalCnt = tatol;
        info.currCnt = currCnt;
        sendto(sockId,&info,sizeof(UPDATE_INFO_RESP),0,&last_client_addr,sizeof(last_client_addr));
    }
}